package git.soulbgm.config;

import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
import git.soulbgm.common.base.BaseDataSourceConfig;
import git.soulbgm.common.enums.DBTypeEnum;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.boot.autoconfigure.quartz.QuartzDataSource;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.env.Environment;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
import tk.mybatis.spring.annotation.MapperScan;

import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;

/**
 * 主从数据源配置
 *
 * @author 贺瑞杰
 * @date 2020/08/27
 */
@Configuration
@MapperScan(basePackages = "git.soulbgm.mapper", sqlSessionTemplateRef = "masterSlaveSqlSessionTemplate")
public class MasterSlaveDataSourceConfig extends BaseDataSourceConfig implements EnvironmentAware {

    private DataSource masterDataSource;
    private DataSource slaveDataSource;

    private static boolean EXIST_SLAVE = true;

    @Bean("masterDataSource")
    @ConfigurationProperties(prefix = "spring.datasource.master")
    public DataSource masterDataSource() {
        return masterDataSource = DruidDataSourceBuilder.create().build();
    }

    @ConfigurationProperties(prefix = "spring.datasource.slave")
    private void slaveDataSource() {
        slaveDataSource = DruidDataSourceBuilder.create().build();
    }

    @Bean("masterSlaveDataSource")
    @Primary
    @QuartzDataSource
    @Override
    public DataSource dataSource() {
        if (masterDataSource == null) {
            masterDataSource();
        }
        if (slaveDataSource == null && EXIST_SLAVE) {
            slaveDataSource();
        }
        Map<Object, Object> targetDataSources = new HashMap<>();
        targetDataSources.put(DBTypeEnum.MASTER, masterDataSource);
        targetDataSources.put(DBTypeEnum.SLAVE1, EXIST_SLAVE ? slaveDataSource : masterDataSource);
        AbstractRoutingDataSource dataSource = new MasterSlaveRoutingDataSource();
        dataSource.setDefaultTargetDataSource(masterDataSource);
        dataSource.setTargetDataSources(targetDataSources);
        return this.dataSource = dataSource;
    }

    @Bean("masterSlaveSqlSessionFactory")
    @Override
    public SqlSessionFactory sqlSessionFactory() {
        return super.sqlSessionFactory();
    }

    @Bean("masterSlaveTransactionManager")
    @Override
    public DataSourceTransactionManager transactionManager() {
        return super.transactionManager();
    }

    @Bean("masterSlaveSqlSessionTemplate")
    @Override
    public SqlSessionTemplate sqlSessionTemplate() {
        return super.sqlSessionTemplate();
    }

    @Override
    public void setEnvironment(Environment environment) {
        String slaveUrl = environment.getProperty("spring.datasource.slave.url");
        if (slaveUrl == null) {
            EXIST_SLAVE = false;
        }
    }
}
